package com.pn.warehouse.controller;

import com.google.code.kaptcha.Producer;
import com.pn.warehouse.entity.*;
import com.pn.warehouse.service.AuthService;
import com.pn.warehouse.service.UserService;
import com.pn.warehouse.utils.DigestUtil;
import com.pn.warehouse.utils.TokenUtils;
import com.pn.warehouse.utils.WarehouseConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
public class LoginController {

    //注入DefaultKaptcha的bean对象 -- 生成验证码图片的
    @Resource(name = "captchaProducer")
    private Producer producer;

    //注入redis的模版
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    //注入TokenUtils工具类
    @Autowired
    private TokenUtils tokenUtils;

    @Autowired
    private AuthService authService;

    /**
     * 生成验证码
     */
    @RequestMapping("/captcha/captchaImage")
    public void captchaImage(HttpServletResponse response){
        ServletOutputStream outputStream = null;
        try {
            //生成验证码图片的文件
            String text = producer.createText();
            //使用验证码文本生成验证码图片 -- BufferedImage对象就代表生成的验证码图片，在内存中
            BufferedImage image = producer.createImage(text);
            //将验证码文本作为键保存到redis中
            redisTemplate.opsForValue().set(text, "", 30*60, TimeUnit.SECONDS);

            //将验证码图片响应给前端
            //设置响应正文image/jpeg
            response.setContentType("image/jpeg");
            //将验证码图片写给前端
            outputStream = response.getOutputStream();
            //使用响应对象的字节输出流写入验证码图片，自然是给前端写入
            ImageIO.write(image, "jpg", outputStream);
            //刷新
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭字节输出流
            if (outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 用户登录
     * @RequestBody ：表示接受并封装前端传递的用户信息的json数据
     * @param loginUser ：用户登陆的信息
     * @return Result对象 -- 表示向前端响应结果Result对象转的字符串
     */
    @RequestMapping("/login")
    public Result login(@RequestBody LoginUser loginUser){
        //1、拿到用户录入的验证码，并判断验证码是否正确
        String code = loginUser.getVerificationCode();
        if (!redisTemplate.hasKey(code)){
            return Result.err(Result.CODE_ERR_BUSINESS, "验证码错误！");
        }

        //2、根据账号查询该用户信息
        User user = userService.fingUserByCode(loginUser.getUserCode());

        //3、判断账号是否存在
        if (user != null){//账号存在
            //4、判断用户是否已审核
            if (user.getUserState().equals(WarehouseConstants.USER_STATE_PASS)){//用户已审核
                //拿到用户的密码并进行md5加密
                String userPwd = DigestUtil.hmacSign(loginUser.getUserPwd());
                //5、判断密码是否正确
                if (userPwd.equals(user.getUserPwd())){//密码正确
                    //6、生成token并存储到了redis中
                    CurrentUser currentUser = new CurrentUser(user.getUserId(), user.getUserCode(), user.getUserName());
                    String token = tokenUtils.loginSign(currentUser, userPwd);
                    //7、向客户端返回成功信息和token
                    return Result.ok("登陆成功！", token);
                }else {//密码不正确
                    return Result.err(Result.CODE_ERR_BUSINESS, "密码错误！");
                }
            }else {//用户未审核
                return Result.err(Result.CODE_ERR_BUSINESS, "用户未审核！");
            }
        }else {//账号不存在
            return Result.err(Result.CODE_ERR_BUSINESS, "账号不存在！");
        }
    }

    /**
     * 根据token获取当前用户的信息并展示给前端
     * @RequestHeader ：表示将请求头中的Token的值赋值给方法中的参数
     */
    @RequestMapping("/curr-user")
    public Result currentUser(@RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String token){
        //1、对token进行解析，得到当前用户的信息并封装到CurrentUser类中
        CurrentUser currentUser = tokenUtils.getCurrentUser(token);
        //2、将用户信息返回给前端
        return Result.ok(currentUser);
    }

    /**
     * 加载用户权限菜单树
     */
    @RequestMapping("/user/auth-list")
    public Result loadAuthTree(@RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String token){
        //1、在token中拿到当前用户的id
        CurrentUser currentUser = tokenUtils.getCurrentUser(token);
        int userId = currentUser.getUserId();

        //2、执行业务
        List<Auth> authTreeList = authService.findAuthByID(userId);

        //3、返回结果
        return Result.ok(authTreeList);
    }

    /**
     * 退出登录
     */
    @RequestMapping("/logout")
    public Result logout(@RequestHeader(WarehouseConstants.HEADER_TOKEN_NAME) String token){
        //1、从redis中删除token的键
        redisTemplate.delete(token);
        //2、返回响应给前端
        return Result.ok("退出登陆！");
    }

}
